package com.taxshare.tools.util;

/**
 * @Author wangzhen
 * @Date 2020/4/10 10:55
 * @Version 1.0
 * @Description Junior development engineer
 **/

import com.taxshare.tools.annotation.CopyField;
import lombok.extern.slf4j.Slf4j;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class BeanSelfUtils {

    private BeanSelfUtils() {
    }

    /**
     * <h3>拷贝一个对象的属性至另一个对象</h3>
     * <p>
     * 支持两个对象之间不同属性名称进行拷贝，使用注解{@link CopyField}
     * </p>
     *
     * @param originBean 源对象 使用注解{@link CopyField#targetName()}
     * @param targetBean 目标对象 使用注解{@link CopyField#originName()}
     */
    public static void copyBean(Object originBean, Object targetBean) {
        Map<String, Object> originFieldKeyWithValueMap = new HashMap<>(16);
        PropertyDescriptor propertyDescriptor = null;
        //生成源bean的属性及其值的字典
        try {
            generateOriginFieldWithValue(propertyDescriptor, originBean, originFieldKeyWithValueMap, originBean.getClass());
            settingTargetFieldWithValue(propertyDescriptor, targetBean, originFieldKeyWithValueMap, targetBean.getClass());
        } catch (Exception e) {
            log.error("对象copy,originBean参数{},targetBean参数{},异常{}", originBean, targetBean, e);
        }

    }

    /**
     * 生成需要被拷贝的属性字典 属性-属性值<br/>
     * 递归取父类属性值
     *
     * @param propertyDescriptor         属性描述器，可以获取bean中的属性及方法
     * @param originBean                 待拷贝的bean
     * @param originFieldKeyWithValueMap 存放待拷贝的属性和属性值
     * @param beanClass                  待拷贝的class[可能是超类的class]
     */
    private static void generateOriginFieldWithValue(PropertyDescriptor propertyDescriptor, Object originBean, Map<String, Object> originFieldKeyWithValueMap, Class<?> beanClass) throws Exception {
        /**如果不存在超类，那么跳出循环*/
        if (beanClass.getSuperclass() == null) {
            return;
        }
        Field[] originFieldList = beanClass.getDeclaredFields();
        for (Field field : originFieldList) {

            /*获取属性上的注解。如果不存在，使用属性名，如果存在使用注解名*/
            CopyField annotation = field.getAnnotation(CopyField.class);
            String targetName = "";
            if (annotation != null) {
                targetName = annotation.targetName();
            } else {
                targetName = field.getName();
            }
            //初始化
            propertyDescriptor = new PropertyDescriptor(field.getName(), beanClass);
            //获取当前属性的get方法
            Method method = propertyDescriptor.getReadMethod();
            //设置值
            Object value = method.invoke(originBean);
            //设置值
            originFieldKeyWithValueMap.put(targetName, value);

        }
        //生成超类 属性-value
        generateOriginFieldWithValue(propertyDescriptor, originBean, originFieldKeyWithValueMap, beanClass.getSuperclass());
    }

    /**
     * @param propertyDescriptor         属性描述器，获取当前传入属性的（getter/setter）方法
     * @param targetBean                 目标容器bean
     * @param originFieldKeyWithValueMap 待拷贝的属性和属性值
     * @param beanClass                  待设置的class[可能是超类的class]
     */
    private static void settingTargetFieldWithValue(PropertyDescriptor propertyDescriptor, Object targetBean, Map<String, Object> originFieldKeyWithValueMap, Class<?> beanClass) throws Exception {
        /**如果不存在超类，那么跳出循环*/
        if (beanClass.getSuperclass() == null) {
            return;
        }
        Field[] targetFieldList = beanClass.getDeclaredFields();
        for (Field field : targetFieldList) {

            /*获取属性上的注解。如果不存在，使用属性名，如果存在使用注解名*/
            CopyField annotation = field.getAnnotation(CopyField.class);
            String originName = "";
            if (annotation != null) {
                originName = annotation.originName();
            } else {
                originName = field.getName();
            }
            //初始化当前属性的描述器
            propertyDescriptor = new PropertyDescriptor(field.getName(), beanClass);
            //获取当前属性的set方法
            Method method = propertyDescriptor.getWriteMethod();
            method.invoke(targetBean, originFieldKeyWithValueMap.get(originName));

        }
        //设置超类属性
        settingTargetFieldWithValue(propertyDescriptor, targetBean, originFieldKeyWithValueMap, beanClass.getSuperclass());
    }

    private static String REGEX_CHINESE = "[\u4e00-\u9fa5]";// 中文正则

    public static String removerStr(String str) {
        // 去除中文
        Pattern pat = Pattern.compile(REGEX_CHINESE);
        Matcher mat = pat.matcher(str);
        String temp = mat.replaceAll("-");
        return temp.substring(0, temp.length() - 1);
    }

    public static String change(double v) {
        if (v >= 0.0D && v <= 9.99999999999999E12D) {
            long l = Math.round(v * 100.0D);
            if (l == 0L) {
                return "零圆整";
            } else {
                String strValue = l + "";
                int i = 0;
                int j = "万千佰拾亿千佰拾万千佰拾圆角分".length() - strValue.length();
                String rs = "";
                StringBuilder sb = new StringBuilder();
                for (boolean isZero = false; i < strValue.length(); ++j) {
                    char ch = strValue.charAt(i);
                    if (ch == '0') {
                        isZero = true;
                        if ("万千佰拾亿千佰拾万千佰拾圆角分".charAt(j) == 20159 || "万千佰拾亿千佰拾万千佰拾圆角分".charAt(j) == 19975 || "万千佰拾亿千佰拾万千佰拾圆角分".charAt(j) == 20803 || "万千佰拾亿千佰拾万千佰拾圆角分".charAt(j) == 22278) {
                            sb.append("万千佰拾亿千佰拾万千佰拾圆角分".charAt(j));
                            isZero = false;
                        }
                    } else {
                        if (isZero) {
                            rs = rs + "零";
                            isZero = false;
                        }
                        sb.append("零壹贰叁肆伍陆柒捌玖".charAt(ch - 48)).append("万千佰拾亿千佰拾万千佰拾圆角分".charAt(j));
                    }

                    ++i;
                }
                return sb.append("整").toString().replaceAll("亿万", "亿");
            }
        } else if (v < 0.0D) {
            return "(负数)" + change(Math.abs(v));
        } else {
            return "参数非法!";
        }
    }

    /**
     * 识别接口返回的发票类型转换成平台的发票类型代码
     *
     * @param type
     * @return
     */
    public static String convertInvoiceType(String type) {
        switch (type) {
            case "10100":
                return "01";
            case "10104":
                return "03";
            case "10101":
                return "04";
            case "10102":
                return "10";
            case "10103":
                return "11";
            case "10503":
                return "21";
            case "10505":
                return "22";
            case "10506":
                return "23";
            case "10500":
                return "24";
            case "10507":
                return "25";
            case "10400":
                return "26";
            case "10200":
                return "27";
            default:
                return "";
        }
    }
}
